package com.product.aspect;

import com.common.domain.Product;
import java.util.concurrent.TimeUnit;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.reflect.CodeSignature;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Component;

import java.util.HashMap;
import java.util.Map;

/**
 * @author Elias
 * @version 1.0
 * @date 2021-05-11 10:31
 * @description 切面类，用于实现商品的数据缓存
 * @copyright 2021
 */
@Component
@Aspect
public class ProductCache {
  @Autowired private StringRedisTemplate redisTemplate;
  @Autowired private ObjectMapper objectMapper;

  /**
   * 更新或添加商品后缓存
   *
   * @param jp 连接点
   * @param result 切入点返回值
   * @throws JsonProcessingException 抛出
   */
  @AfterReturning(
      value = " execution(* com.product.service.ProductService*.*Product(..))",
      returning = "result")
  public void afterUpdateProduct(JoinPoint jp, Object result) throws JsonProcessingException {
    Map<String, Object> map = new HashMap<>();
    Object[] values = jp.getArgs();
    String[] names = ((CodeSignature) jp.getSignature()).getParameterNames();
    for (int i = 0; i < names.length; i++) {
      map.put(names[i], values[i]);
    }
    Product product = (Product) map.get("product");
    try {
      this.redisTemplate
          .opsForValue()
          .set(
              "PROD_" + product.getProductId(),
              objectMapper.writeValueAsString(product),
              30,
              TimeUnit.MINUTES);
    } catch (JsonProcessingException e) {
      e.printStackTrace();
    }
  }

  /**
   * 查询商品后返回
   *
   * @param jp 连接点
   * @param result 切入点返回值
   */
  @AfterReturning(
      value = " execution(* com.product.service.ProductService*.QueryByProductId(..))",
      returning = "result")
  public void afterQueryProduct(JoinPoint jp, Object result) {
    Map<String, Object> map = new HashMap<>();
    String[] names = ((CodeSignature) jp.getSignature()).getParameterNames();
    Object[] values = jp.getArgs();
    for (int i = 0; i < names.length; i++) {
      map.put(names[i], values[i]);
    }
    String productId = (String) map.get("productId");
    try {
      this.redisTemplate.expire("PROD_" + productId, 30, TimeUnit.MINUTES);
    } catch (Exception e) {
      e.printStackTrace();
    }
  }
}
